﻿#ifndef ITEMSCENE_H
#define ITEMSCENE_H

#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QString>
#include <QMap>
#include <QVector>

#include <QMimeData>
#include <QDrag>
#include <QGraphicsSceneDragDropEvent>
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDragMoveEvent>
#include <QDropEvent>
#include <QKeyEvent>
#include <QMap>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

#include <QDebug>

#include <QGraphicsLineItem>
#include "../../tools/headers/MimeData.h"
#include "../../beans/headers/FlowBlockItem.h"
#include "../../beans/headers/LineItemClass.h"
#include "../../tools/headers/EnumHeader.h"



class BlockItemClass;
class ItemScene : public QGraphicsScene
{
    Q_OBJECT
public:
    ItemScene(int blockItemLastID = 1,int lineItemLastID = 1,QObject *parent = nullptr);
    ~ItemScene();

    // 获取鼠标在场景中的实时坐标
    QPointF getCursorPos();

    // 将场景转化为json格式
    QJsonDocument toJsonDoc(void);

    // 清除场景中的所有Item
    void clear(void);

    // 将BlockItemClass插入Map中
    void setBlockItemClassInsertIntoBlockMap(int blockID,BlockItemClass *blockItemClass);

    // 将BlockItemClass插入Map中
    void setLineItemClassInsertIntoLineList(LineItemClass *lineItemClass);

    QMap<int, BlockItemClass *> getBlockItemClass_Map() const;

    QList<LineItemClass *> getLineItemClass_List() const;



protected:
    void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
    void dropEvent(QGraphicsSceneDragDropEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);
    void keyReleaseEvent(QKeyEvent *event);

signals:
    // 发送鼠标所在的坐标
    void signal_CurrCursorPos(QPointF cursorPos);

    // 发送鼠标所在Item的类型
    void signal_CurrCursorPosItemClass(QString itemClass);

    // 为了检测场景中鼠标是否和BlockItem碰撞
    void signal_currCursorPosToFlowBlockItem(QPointF cursorPos);



private:
    // 辅助函数（向场景中添加模块）
    void addFlowBlockItem(int itemTypeID,QPointF cursor_Pos);

    // 辅助函数(返回一个矩形中的BlcokItem)
    QList<FlowBlockItem *> itemsAtRect(QPointF leftTopPoint,
                                       QPointF RightButtomPoint,

                                       // 与选择矩形区域相交和被包涵在选择矩形区域中的
                                       Qt::ItemSelectionMode mode = Qt::IntersectsItemShape,
                                       Qt::SortOrder order = Qt::AscendingOrder,
                                       const QTransform &deviceTransform = QTransform()) const;

    // 辅助函数（场景中被选中的父界别Item）
    QList<QGraphicsItem *> fatherItemsBySelected(void);

    // 辅助函数（缩放BlockItem）
    void zoomBlockItem(SquareItem *squareItem,QPointF cursorPos);

    // 辅助函数（根据当前的的父级别ItemScene的大小）
    void updateSceneRect(QGraphicsItem *fatherItem);

    // 辅助函数（通过枚举ItemClass，返回对应的字符串）
    QString itemClass2String(int itemClass);

    // 辅助函数（鼠标释放是否确定画线）
    void whetherDrawLine(QGraphicsItem *cursorItem,QList<LineItemClass *> &lineItemClass_List);

    // 辅助函数（移动线）
    void moveLineItem(FlowLineItem *lineItem,QPointF cursorPos);

    // 辅助函数（移动模块）
    void moveBlockItem(FlowBlockItem *cursorBlockItem);

    // 更新该模块矩形区域的刷新显示
    void updateRectShow(FlowBlockItem *blockItem);

private:
    // 用于标记最后一次的BlockItemID
    int m_FlowBlockItemLastID;

    // 用于标记最后一次的LineItemID
    int m_FlowLineItemLastID;

    // 鼠标按下标记
    bool m_IsMousePressed;

    // 用于同时捕获多个键盘的事件
    QList<int> m_KeyCommand;

    // 用于缩放的Item指针,因为这样可以避免因鼠标拖动太快而导致交互不通顺（在鼠标按压、释放和移动事件中使用了）
    QGraphicsItem *m_MousePressItem = Q_NULLPTR;

    // 所有线的链接
    QList<LineItemClass *> m_LineItemClass_List;

    // BlockItem集合
    QMap<int , BlockItemClass *> m_BlockItemClass_Map;

    // 场景中实时鼠标坐标
    QPointF m_CurrCusrsorPos;
};

#endif // ITEMSCENE_H
